﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace XWord.WPF.Behaviors
{
    public class MulitItemSelectBehavior : Behavior<ListBox>
    {

        public IEnumerable SelectedItems
        {
            get { return (IEnumerable)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems", typeof(IEnumerable), typeof(MulitItemSelectBehavior),
            new UIPropertyMetadata((s, a) =>
            {
                var element = s as MulitItemSelectBehavior;
                if (element.AssociatedObject == null) return;
                element.UnRegister();
                element.AssociatedObject.SelectedItem = null;
                element.AssociatedObject.Dispatcher.BeginInvoke(new Action(() =>
                {
                    element.AssociatedObject.SelectItems(a.NewValue as IEnumerable);
                    element.Register();
                }), System.Windows.Threading.DispatcherPriority.Normal);

            }));

        private void UnRegister()
        {
            AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
        }

        private void Register()
        {
            AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
        }

        void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (SelectedItems == null) return;
            foreach (var item in e.AddedItems)
            {
                SelectedItems.GetType().GetMethod("Add").Invoke(SelectedItems, new object[] { item });
            }
            foreach (var item in e.RemovedItems)
            {
                SelectedItems.GetType().GetMethod("Remove").Invoke(SelectedItems, new object[] { item });
            }
        }
    }

    public static class ListBoxExtension
    {
        public static void SelectItems(this ListBox box, IEnumerable items)
        {
            if (items == null) return;
            ;
            var SelectionChange = box.GetType().GetProperty("SelectionChange", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(box, null);
            var t = SelectionChange.GetType();
            t.GetMethod("Begin", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(SelectionChange, null);
            t.GetMethod("CleanupDeferSelection", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(SelectionChange, null);
            try
            {
                var methodInfo = t.GetMethod("Select", BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (object obj2 in items)
                {
                    methodInfo.Invoke(SelectionChange, new object[] { obj2, true });
                }
            }
            finally
            {
                t.GetMethod("End", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(SelectionChange, null);
            }
        }
    }
}
